/*
 * Code for blog.techhead.biz
 * Distributed under BSD-style license
 */
package biz.techhead.funcy;

import biz.techhead.funcy.Step.Stepper;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * Ranges provides declarative Range support for Java.  Its syntax was inspired
 * by the {@code LOOP} construct in Common Lisp.
 * 
 * <p>This class provides {@link biz.techhead.funcy.Range} implementations for
 * all the primitive wrapper types: {@code Character, Byte, Short, Integer,
 * Long, Float, Double}. It also supports {@code Enum, Date, BigInteger,
 * BigDecimal} and any other class which implements {@code Comparable}.
 *
 * <p>All {@code Range} implementations provided by this class are Thread safe.
 * 
 * <code><pre>&nbsp;{@literal
 * 
 * // Usage examples
 * 
 * for (char c : Ranges.from('A').to('Z') ) {
 *     // do something
 * }
 * 
 * // descending ranges are also supported
 * for (int i : Ranges.from(10).to(1) ) {
 *     // ...
 * }
 * 
 * // as are explicitly descending ranges
 * int x = 11;
 * for (int i : Ranges.downFrom(10).to(x) ) {
 *     // will never get here
 * }
 *
 * // exclusive ranges (counts from 0 to 9)
 * for (int i : Ranges.from(0).to(10).exclusive() ) {
 *     // ...
 * }
 *
 * // set your own increment
 * // support for open ranges
 * // find all even integers from 2 to Integer.MAX_VALUE
 * for (int i : Ranges.upFrom(2).by(2) ) {
 *     // ...
 * }
 *
 * // Enum support
 * enum Digit {ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE};
 * for (Digit d : Ranges.from(Digit.NINE).to(Digit.FIVE) ) {
 *     // ...
 * }
 *
 * 
 * // Date support
 * Date date = ...;
 *
 * // An open Date range by day
 * for (Date nextDay : Ranges.from(date) ) {
 *     // ...
 * }
 *
 * // An open Date range descending by hour
 * for (Date prevHour : Ranges.downFrom(date).by(Calendar.HOUR) ) {
 *     // ...
 * }
 * 
 * }</pre></code>
 *
 * @author Jonathan Hawkes <jhawkes at techhead.biz>
 */
public class Ranges {
    
    // prevent instantiation
    private Ranges() {}

    /**
     * Run a series of metrics comparing the performance of this class to
     * various other solutions.
     */

    /*
    private static Iterable<Integer> mostNaive(final int from,
                                               final int toExcluded) {
        return new Iterable<Integer>() {

            public Iterator<Integer> iterator() {
                return new Iterator<Integer>() {
                    
                    int current = from;

                    public boolean hasNext() {
                        return current < toExcluded;
                    }

                    public Integer next() {
                        return current++;
                    }

                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    private static class SummingVisitor implements Func<Void,Integer> {

        long sum = 0;

        public Void call(Integer in) {
            sum += in;
            return null;
        }
    }

    public static void main(String[] args) {
        long sum, startTime, endTime;
        
        sum = 0;
        startTime = System.currentTimeMillis();
        for (int i=0; i<Integer.MAX_VALUE; i++) {
            sum += i;
        }
        endTime = System.currentTimeMillis();
        long baselinetime = endTime - startTime;
        System.out.println("sum = " + sum);
        System.out.println("baselinetime = " + baselinetime);
        
        sum = 0;
        startTime = System.currentTimeMillis();
        for (Integer i=0; i<Integer.MAX_VALUE; i++) {
            sum += i;
        }
        endTime = System.currentTimeMillis();
        long autoboxtime = endTime - startTime;
        System.out.println("sum = " + sum);
        System.out.println("autoboxtime = " + autoboxtime);
        System.out.println("autoboxtime/baselinetime = " +
                ((double)autoboxtime)/baselinetime);
        
        sum = 0;
        startTime = System.currentTimeMillis();
        for (Integer i : Ranges.upFrom(0,Integer.MAX_VALUE).exclusive()) {
            sum += i;
        }
        endTime = System.currentTimeMillis();
        long rangetime = endTime - startTime;
        System.out.println("sum = " + sum);
        System.out.println("rangetime = " + rangetime);
        System.out.println("rangetime/baselinetime = " +
                ((double)rangetime)/baselinetime);

        sum = 0;
        startTime = System.currentTimeMillis();
        for (Integer i : mostNaive(0, Integer.MAX_VALUE)) {
            sum += i;
        }
        endTime = System.currentTimeMillis();
        long naivetime = endTime - startTime;
        System.out.println("sum = " + sum);
        System.out.println("naivetime = " + naivetime);
        System.out.println("naivetime/baselinetime = " +
                ((double)naivetime)/baselinetime);
        
        SummingVisitor visitor = new SummingVisitor();
        startTime = System.currentTimeMillis();
        for (int i=0; i<Integer.MAX_VALUE; i++) {
            visitor.call(i);
        }
        endTime = System.currentTimeMillis();
        long visitortime = endTime - startTime;
        System.out.println("sum = " + visitor.sum);
        System.out.println("visitortime = " + visitortime);
        System.out.println("visitortime/baselinetime = " +
                ((double)visitortime)/baselinetime);
    }
    */
    
    /**
     * An OpenRange has a start point (inclusive) but no end point
     * (unless the Range has a natural end point such as with a Range of
     * Integer and Integer.MAX_VALUE).
     */
    public static interface OpenRange<T extends Comparable<T>>
            extends Range<T> {

        /**
         * Takes an end point as a parameter and returns a new
         * InclusiveRange that uses the same start point as this
         * OpenRange.
         * @throws NullPointerException if last is null
         */
        InclusiveRange<T> to(T last);
    }

    /**
     * An InclusiveRange has both a start and end point (inclusive).
     */
    public static interface InclusiveRange<T extends Comparable<T>>
            extends Range<T> {

        /**
         * Returns a new Range that is the same as this one
         * minus the end point.
         */
        Range<T> exclusive();
    }

    /**
     * An IterableRange has a natural (default) iteration order in addition
     * to those specified by {@link #by(Number) by}.
     */
    public static interface IterableRange<T extends Comparable<T>>
            extends Range<T>, Iterable<T> {

        @Override Iterator<T> iterator();

        /**
         * Given a selector, this will return an Iterable to iterate over
         * this range in some implementation-specific way.
         * @throws IllegalArgumentException if the selector is not understood
         * @throws NullPointerException if the selector is null
         */
        Iterable<T> by(Number selector);
    }

    /**
     * @see Ranges.OpenRange OpenRange
     * @see Ranges.IterableRange IterableRange
     */
    public static interface OpenIterableRange<T extends Comparable<T>>
            extends OpenRange<T>, IterableRange<T> {
        @Override InclusiveIterableRange<T> to(T last);
    }

    /**
     * @see Ranges.InclusiveRange InclusiveRange
     * @see Ranges.IterableRange IterableRange
     */
    public static interface InclusiveIterableRange<T extends Comparable<T>>
            extends InclusiveRange<T>, IterableRange<T> {
        @Override IterableRange<T> exclusive();
    }

    /**
     * Returns an OpenRange that is ascending by default, but will become
     * descending if given an end point that is comparatively lower than
     * the start point.
     * 
     * @param <T> The Comparable type of Range to build.
     * @param from The included start point of the Range.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>> OpenRange<T> from(T from) {
        return from( ( StepProvider<T> ) noStepProvider, from );
    }

    /**
     * Returns an InclusiveRange.  Whether this Range is ascending or
     * descending depends on the comparative value of the start and end points.
     *
     * @param <T> The Comparable type of Range to build.
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>>
            InclusiveRange<T> from(T from, T to) {
        return from( ( StepProvider<T> ) noStepProvider, from, to );
    }

    /**
     * Returns an OpenRange that is ascending regardless of the end point
     * applied later.  If the end point is comparatively less than the
     * start point, the Range will be empty.
     *
     * @param <T> The Comparable type of Range to build.
     * @param from The included start point of the Range.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>> OpenRange<T> upFrom(T from) {
        return upFrom( ( StepProvider<T> ) noStepProvider, from );
    }

    /**
     * Returns an InclusiveRange that is ascending regardless of the
     * given end point.  If the end point is comparatively less than the
     * start point, the Range will be empty.
     * 
     * @param <T> The Comparable type of Range to build.
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>>
            InclusiveRange<T> upFrom(T from, T to) {
        return upFrom( ( StepProvider<T> ) noStepProvider, from, to );
    }

    /**
     * Returns an OpenRange that is descending regardless of the end point
     * applied later.  If the end point is comparatively greater than the
     * start point, the Range will be empty.
     *
     * @param <T> The Comparable type of Range to build.
     * @param from The included start point of the Range.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>> OpenRange<T> downFrom(T from) {
        return downFrom( ( StepProvider<T> ) noStepProvider, from );
    }

    /**
     * Returns an InclusiveRange that is ascending regardless of the
     * given end point.  If the end point is comparatively greater than the
     * start point, the Range will be empty.
     *
     * @param <T> The Comparable type of Range to build.
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     */
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>>
            InclusiveRange<T> downFrom(T from, T to) {
        return downFrom( ( StepProvider<T> ) noStepProvider, from, to );
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the created
     * Range is also Iterable.  The default step between one Enum and the next
     * is a single ordinal.  To step by more than 1, use the
     * {@link Ranges.IterableRange#by(Number) by} method with a different
     * Integer argument (eg. {@code range.by(2)}).
     *
     * @param <E> The Enum type of the Range to build
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static <E extends Enum<E>>
            OpenIterableRange<E> from(E from) {
        return from(stepProvider(from), from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step between
     * one Enum and the next is a single ordinal.  To step by more than 1, use
     * the {@link Ranges.IterableRange#by(Number) by} method with a different
     * Integer argument (eg. {@code range.by(2)}).
     *
     * @param <E> The Enum type of the Range to build
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static <E extends Enum<E>>
            InclusiveIterableRange<E> from(E from, E to) {
        return from(stepProvider(from), from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step between one Enum and
     * the next is a single ordinal.  To step by more than 1, use the
     * {@link Ranges.IterableRange#by(Number) by} method with a different
     * Integer argument (eg. {@code range.by(2)}).
     *
     * @param <E> The Enum type of the Range to build
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static <E extends Enum<E>>
            OpenIterableRange<E> upFrom(E from) {
        return upFrom(stepProvider(from), from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step between
     * one Enum and the next is a single ordinal.  To step by more than 1, use
     * the {@link Ranges.IterableRange#by(Number) by} method with a different
     * Integer argument (eg. {@code range.by(2)}).
     *
     * @param <E> The Enum type of the Range to build
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static <E extends Enum<E>>
            InclusiveIterableRange<E> upFrom(E from, E to) {
        return upFrom(stepProvider(from), from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step between one Enum and
     * the next is a single ordinal.  To step by more than 1, use the
     * {@link Ranges.IterableRange#by(Number) by} method with a different
     * Integer argument (eg. {@code range.by(2)}).
     *
     * @param <E> The Enum type of the Range to build
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static <E extends Enum<E>>
            OpenIterableRange<E> downFrom(E from) {
        return downFrom(stepProvider(from), from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)} except that the created Range is also
     * Iterable.  The default step between one Enum and the next is a single
     * ordinal.  To step by more than 1, use the
     * {@link Ranges.IterableRange#by(Number) by} method with a different
     * Integer argument (eg. {@code range.by(2)}).
     *
     * @param <E> The Enum type of the Range to build
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static <E extends Enum<E>>
            InclusiveIterableRange<E> downFrom(E from, E to) {
        return downFrom(stepProvider(from), from, to);
    }
    
    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step between one Date and
     * the next is a single day.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a field value from the Calendar class as an argument
     * (eg. {@code range.by(Calendar.MONTH)}).
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Date> from(Date from) {
        return from(dateStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step between
     * one Date and the next is a single day.
     * The {@link Ranges.IterableRange#by(Number) by} method takes a field value
     * from the Calendar class as an argument
     * (eg. {@code range.by(Calendar.MONTH)}).
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Date>
            from(Date from, Date to) {
        return from(dateStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step between one Date and
     * the next is a single day.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a field value from the Calendar class as an argument
     * (eg. {@code range.by(Calendar.MONTH)}).  Like all ranges created from
     * the Ranges class, the returned Range is thread safe.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Date> upFrom(Date from) {
        return upFrom(dateStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step between
     * one Date and the next is a single day.
     * The {@link Ranges.IterableRange#by(Number) by} method takes a field value
     * from the Calendar class as an argument
     * (eg. {@code range.by(Calendar.MONTH)}).
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Date>
            upFrom(Date from, Date to) {
        return upFrom(dateStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step between one Date and
     * the next is a single day.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a field value from the Calendar class as an argument
     * (eg. {@code range.by(Calendar.MONTH)}).
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Date> downFrom(Date from) {
        return downFrom(dateStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)} except that the created Range is also
     * Iterable.  The default step between one Date and the next is a single
     * day. The {@link Ranges.IterableRange#by(Number) by} method takes a field
     * value from the Calendar class as an argument
     * (eg. {@code range.by(Calendar.MONTH)}).
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Date>
            downFrom(Date from, Date to) {
        return downFrom(dateStepProvider, from, to);
    }    

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single Character.
     * The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number of characters to skip (eg. {@code range.by(2)}).
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Character> from(Character from) {
        return from(charStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single Character.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number of characters to skip (eg. {@code range.by(2)}).
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Character>
            from(Character from, Character to) {
        return from(charStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single Character.
     * The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number of characters to skip (eg. {@code range.by(2)}).
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Character> upFrom(Character from) {
        return upFrom(charStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single Character.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number of characters to skip (eg. {@code range.by(2)}).
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Character>
            upFrom(Character from, Character to) {
        return upFrom(charStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single Character.
     * The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number of characters to skip (eg. {@code range.by(2)}).
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Character> downFrom(Character from) {
        return downFrom(charStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)} except that the created Range is also
     * Iterable.  The default step is a single Character.
     * The {@link Ranges.IterableRange#by(Number) by} method takes a Number of
     * characters to skip (eg. {@code range.by(2)}).
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Character>
            downFrom(Character from, Character to) {
        return downFrom(charStepProvider, from, to);
    }    

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Byte> from(Byte from) {
        return from(byteStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Byte> from(Byte from, Byte to) {
        return from(byteStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Byte> upFrom(Byte from) {
        return upFrom(byteStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Byte>
            upFrom(Byte from, Byte to) {
        return upFrom(byteStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Byte> downFrom(Byte from) {
        return downFrom(byteStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Byte>
            downFrom(Byte from, Byte to) {
        return downFrom(byteStepProvider, from, to);
    }    
    
    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Short> from(Short from) {
        return from(shortStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Short>
            from(Short from, Short to) {
        return from(shortStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Short> upFrom(Short from) {
        return upFrom(shortStepProvider, from);
    }
    
    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Short>
            upFrom(Short from, Short to) {
        return upFrom(shortStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Short> downFrom(Short from) {
        return downFrom(shortStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Short>
            downFrom(Short from, Short to) {
        return downFrom(shortStepProvider, from, to);
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Integer> from(Integer from) {
        return from(intStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Integer>
            from(Integer from, Integer to) {
        return from(intStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Integer> upFrom(Integer from) {
        return upFrom(intStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Integer>
            upFrom(Integer from, Integer to) {
        return upFrom(intStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Integer> downFrom(Integer from) {
        return downFrom(intStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Integer>
            downFrom(Integer from, Integer to) {
        return downFrom(intStepProvider, from, to);
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Long> from(Long from) {
        return from(longStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Long> from(Long from, Long to) {
        return from(longStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Long> upFrom(Long from) {
        return upFrom(longStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Long>
            upFrom(Long from, Long to) {
        return upFrom(longStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Long> downFrom(Long from) {
        return downFrom(longStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Long>
            downFrom(Long from, Long to) {
        return downFrom(longStepProvider, from, to);
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Float> from(Float from) {
        return from(floatStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Float>
            from(Float from, Float to) {
        return from(floatStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Float> upFrom(Float from) {
        return upFrom(floatStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Float>
            upFrom(Float from, Float to) {
        return upFrom(floatStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Float> downFrom(Float from) {
        return downFrom(floatStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Float>
            downFrom(Float from, Float to) {
        return downFrom(floatStepProvider, from, to);
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<Double> from(Double from) {
        return from(doubleStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Double>
            from(Double from, Double to) {
        return from(doubleStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<Double> upFrom(Double from) {
        return upFrom(doubleStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Double>
            upFrom(Double from, Double to) {
        return upFrom(doubleStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<Double> downFrom(Double from) {
        return downFrom(doubleStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * <p>Floating-point ranges may have unanticipated behavior.  For a further
     * explanation, see the introduction to {@link Ranges}.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<Double>
            downFrom(Double from, Double to) {
        return downFrom(doubleStepProvider, from, to);
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     * 
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<BigInteger> from(BigInteger from) {
        return from(BigIntegerStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<BigInteger>
            from(BigInteger from, BigInteger to) {
        return from(BigIntegerStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<BigInteger> upFrom(BigInteger from) {
        return upFrom(BigIntegerStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<BigInteger>
            upFrom(BigInteger from, BigInteger to) {
        return upFrom(BigIntegerStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<BigInteger>
            downFrom(BigInteger from) {
        return downFrom(BigIntegerStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<BigInteger>
            downFrom(BigInteger from, BigInteger to) {
        return downFrom(BigIntegerStepProvider, from, to);
    }

    /**
     * Like {@link #from(Comparable) from(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #from(Comparable) from(Comparable)
     */
    public static OpenIterableRange<BigDecimal> from(BigDecimal from) {
        return from(BigDecimalStepProvider, from);
    }

    /**
     * Like {@link #from(Comparable,Comparable) from(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @param to The included end point of the Range.
     * @see #from(Comparable,Comparable) from(Comparable,Comparable)
     */
    public static InclusiveIterableRange<BigDecimal>
            from(BigDecimal from, BigDecimal to) {
        return from(BigDecimalStepProvider, from, to);
    }

    /**
     * Like {@link #upFrom(Comparable) upFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable) upFrom(Comparable)
     */
    public static OpenIterableRange<BigDecimal> upFrom(BigDecimal from) {
        return upFrom(BigDecimalStepProvider, from);
    }

    /**
     * Like {@link #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     *
     * @param from The included start point of the Range.
     * @see #upFrom(Comparable,Comparable) upFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<BigDecimal>
            upFrom(BigDecimal from, BigDecimal to) {
        return upFrom(BigDecimalStepProvider, from, to);
    }

    /**
     * Like {@link #downFrom(Comparable) downFrom(Comparable)} except that the
     * created Range is also Iterable.  The default step is a single whole
     * Number.  The {@link Ranges.IterableRange#by(Number) by} method takes a
     * Number (eg. {@code range.by(2)}) that will be used to step through the
     * Range.
     *
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable) downFrom(Comparable)
     */
    public static OpenIterableRange<BigDecimal>
            downFrom(BigDecimal from) {
        return downFrom(BigDecimalStepProvider, from);
    }    

    /**
     * Like {@link #downFrom(Comparable,Comparable)
     * downFrom(Comparable,Comparable)}
     * except that the created Range is also Iterable.  The default step is a
     * single whole Number.  The {@link Ranges.IterableRange#by(Number) by}
     * method takes a Number (eg. {@code range.by(2)}) that will be used to step
     * through the Range.
     * 
     * @param from The included start point of the Range.
     * @see #downFrom(Comparable,Comparable) downFrom(Comparable,Comparable)
     */
    public static InclusiveIterableRange<BigDecimal>
            downFrom(BigDecimal from, BigDecimal to) {
        return downFrom(BigDecimalStepProvider, from, to);
    }

    private static final <T extends Comparable<T>>
            OpenIterableRange<T> from(StepProvider<T> provider, T from) {
        return new AscendingOpenRange<T>(provider, from) {
            @Override
            public InclusiveIterableRange<T> to(T end) {
                if (lower.compareTo(end) > 0) {
                    return downFrom(provider, lower, end);
                }
                return super.to(end);
            }
        };
    }

    private static final <T extends Comparable<T>>
            InclusiveIterableRange<T> from(StepProvider<T> provider,
                                           T from, T to) {
        if (from.compareTo(to) > 0)
            return downFrom(provider, from, to);
        return upFrom(provider, from, to);
    }

    private static final <T extends Comparable<T>>
            OpenIterableRange<T> upFrom(StepProvider<T> provider, T from) {
        return new AscendingOpenRange<T>(provider, from);
    }

    private static final <T extends Comparable<T>>
            InclusiveIterableRange<T> upFrom(StepProvider<T> provider,
                                             T from, T to) {
        return new AscendingInclusiveRange<T>(provider, from, to);
    }

    private static final <T extends Comparable<T>>
            OpenIterableRange<T> downFrom(StepProvider<T> provider, T from) {
        return new DescendingOpenRange<T>(provider, from);
    }    

    private static final <T extends Comparable<T>>
            InclusiveIterableRange<T> downFrom(StepProvider<T> provider,
                                               T from, T to) {
        return new DescendingInclusiveRange<T>(provider, from, to);
    }    

    private static abstract class AbstractRange<T extends Comparable<T>>
            implements IterableRange<T> {

        final StepProvider<T> provider;

        AbstractRange(StepProvider<T> provider) {
            this.provider = provider;
        }

        @Override
        public final boolean contains(T item) {
            return (item == null) ? false :
                containedByLowerBound(item) &&
                containedByUpperBound(item);
        }

        @Override
        public final Iterator<T> iterator() {
            return iteratorFor( provider.step() );
        }

        @Override
        public final Iterable<T> by(Number selector) {
            return by( provider.stepFor(selector) );
        }

        @Override
        public final Iterable<T> by(final Step<T> step) {
            return new Iterable<T>() {
                public Iterator<T> iterator() {
                    return iteratorFor(step);
                }
            };
        }

        abstract boolean containedByLowerBound(T item);
        abstract boolean containedByUpperBound(T item);
        abstract Iterator<T> iteratorFor(Step<T> step);
    }

    private static abstract class AscendingRange<T extends Comparable<T>>
            extends AbstractRange<T> {

        final T lower;

        AscendingRange(StepProvider<T> provider, T lower) {
            super(provider);
            this.lower = lower;
        }

        @Override
        final Iterator<T> iteratorFor(Step<T> step) {
            final Stepper<T> stepper = step.stepper(lower);
            return new Iterator<T>() {
                T cursor = lower;
                boolean hasNext = containedByUpperBound(cursor);

                public boolean hasNext() { return hasNext; }

                public T next() {
                    if (hasNext) {
                        T next = cursor;
                        try {
                            cursor = stepper.stepUp();
                            if ( !containedByUpperBound(cursor) )
                                hasNext = false;
                        } catch (NoSuchElementException e) {
                            hasNext = false;
                        }
                        return next;
                    }
                    throw new NoSuchElementException();
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }

        @Override
        final boolean containedByLowerBound(T item) {
            return (item.compareTo(lower) >= 0);            
        }        
    }

    private static abstract class DescendingRange<T extends Comparable<T>>
            extends AbstractRange<T> {

        final T upper;

        DescendingRange(StepProvider<T> provider, T upper) {
            super(provider);
            this.upper = upper;
        }

        @Override
        final Iterator<T> iteratorFor(Step<T> step) {
            final Stepper<T> stepper = step.stepper(upper);
            return new Iterator<T>() {
                T cursor = upper;
                boolean hasNext = containedByLowerBound(cursor);

                public boolean hasNext() { return hasNext; }

                public T next() {
                    if (hasNext) {
                        T next = cursor;
                        try {
                            cursor = stepper.stepDown();
                            if ( !containedByLowerBound(cursor) )
                                hasNext = false;
                        } catch (NoSuchElementException e) {
                            hasNext = false;
                        }
                        return next;
                    }
                    throw new NoSuchElementException();
                }

                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }

        @Override
        final boolean containedByUpperBound(T item) {
            return (item.compareTo(upper) <= 0);
        }
    }
    
    private static class AscendingOpenRange<T extends Comparable<T>>
            extends AscendingRange<T> implements OpenIterableRange<T> {

        AscendingOpenRange(StepProvider<T> provider, T lower) {
            super(provider, lower);
        }

        @Override
        public InclusiveIterableRange<T> to(T upper) {
            return new AscendingInclusiveRange<T>(provider, lower, upper);
        }

        @Override
        final boolean containedByUpperBound(T item) {
            return true;
        }
    }

    private static class AscendingInclusiveRange<T extends Comparable<T>>
            extends AscendingRange<T> implements InclusiveIterableRange<T> {

        final T upper;

        AscendingInclusiveRange(StepProvider<T> provider, T lower, T upper) {
            super(provider, lower);
            this.upper = upper;
        }

        @Override
        public final AscendingExclusiveRange<T> exclusive() {
            return new AscendingExclusiveRange<T>(provider, lower, upper);
        }

        @Override
        final boolean containedByUpperBound(T item) {
            return (item.compareTo(upper) <= 0);
        }
    }

    private static class AscendingExclusiveRange<T extends Comparable<T>>
            extends AscendingRange<T> {

        final T upper;

        AscendingExclusiveRange(StepProvider<T> provider, T lower, T upper) {
            super(provider, lower);
            this.upper = upper;
        }

        @Override
        final boolean containedByUpperBound(T item) {
            return (item.compareTo(upper) < 0);
        }
    }
    
    private static class DescendingOpenRange<T extends Comparable<T>>
            extends DescendingRange<T> implements OpenIterableRange<T> {

        DescendingOpenRange(StepProvider<T> provider, T upper) {
            super(provider, upper);
        }

        @Override
        public final DescendingInclusiveRange<T> to(T lower) {
            return new DescendingInclusiveRange<T>(provider, upper, lower);
        }

        @Override
        final boolean containedByLowerBound(T item) {
            return true;
        }
    }

    private static class DescendingInclusiveRange<T extends Comparable<T>>
            extends DescendingRange<T>
            implements InclusiveIterableRange<T> {

        final T lower;

        DescendingInclusiveRange(StepProvider<T> provider, T upper, T lower) {
            super(provider, upper);
            this.lower = lower;
        }

        @Override
        public final DescendingExclusiveRange<T> exclusive() {
            return new DescendingExclusiveRange<T>(provider, upper, lower);
        }

        @Override
        final boolean containedByLowerBound(T item) {
            return (item.compareTo(lower) >= 0);            
        }
    }

    private static class DescendingExclusiveRange<T extends Comparable<T>>
            extends DescendingRange<T> {

        final T lower;

        DescendingExclusiveRange(StepProvider<T> provider, T upper, T lower) {
            super(provider, upper);
            this.lower = lower;
        }

        @Override
        final boolean containedByLowerBound(T item) {
            return (item.compareTo(lower) > 0);            
        }
    }

    private static interface StepProvider<T> {
        Step<T> step();
        Step<T> stepFor(Number n);
    }
        
    private static abstract class AbstractStepProvider<T>
            implements StepProvider<T> {
        private final Step<T> defaultStep;
        AbstractStepProvider() { defaultStep = stepFor(1); }
        @Override public final Step<T> step() { return defaultStep; }
        @Override public abstract Step<T> stepFor(Number num);
    }

    private static final StepProvider<?> noStepProvider =
            new StepProvider<Object>() {

        public Step<Object> step() {
            throw new UnsupportedOperationException();
        }

        public Step<Object> stepFor(Number n) {
            throw new UnsupportedOperationException();
        }
    };

    private static class EnumStepProvider<E extends Enum<E>>
            extends AbstractStepProvider<E> {

        private final List<E> values;

        EnumStepProvider(Class<E> enumClass) {
            values = Enums.values(enumClass);
        }

        public Step<E> stepFor(Number n) {
            final int skip = Math.abs(n.intValue());
            return new Step<E>() {
                public Stepper<E> stepper(final E point) {
                    return new Stepper<E>() {
                        
                        int ordinal = point.ordinal();

                        public E value() { return values.get(ordinal); }

                        public E stepUp() {
                            int i = ordinal + skip;
                            if (i < values.size()) {
                                ordinal = i;
                                return values.get(i);
                            }
                            throw new NoSuchElementException();
                        }

                        public E stepDown() {
                            int i = ordinal - skip;
                            if (i >= 0) {
                                ordinal = i;
                                return values.get(i);
                            }
                            throw new NoSuchElementException();
                        }
                    };
                }
            };
        }
    }

    private static final <E extends Enum<E>>
            EnumStepProvider<E> stepProvider(E e) {
        return new EnumStepProvider<E>( e.getDeclaringClass() );
    }
    
    private static class DateStep implements Step<Date> {

        private final int calendarField;

        DateStep(int calendarField) {
            this.calendarField = calendarField;
        }
 
        public Stepper<Date> stepper(Date point) {
            final Calendar cal = Calendar.getInstance();
            cal.setTime(point);
            return new Stepper<Date>() {

                public Date value() { return cal.getTime(); }
                public Date stepUp() { return step(1); }
                public Date stepDown() { return step(-1); }
 
                Date step(int i) {
                    cal.add(calendarField, i);
                    return cal.getTime();
                }
            };
        }
    }

    private static final StepProvider<Date> dateStepProvider =
            new StepProvider<Date>() {

        final Step<Date> oneDay = new DateStep(Calendar.DATE);

        public Step<Date> step() { return oneDay; }

        public Step<Date> stepFor(Number calendarField) {
            return new DateStep(calendarField.intValue());
        }
    };

    private static class IntStep {

        private final int amount, upper, lower;

        IntStep(Number amt, int max, int min) {
            amount = Math.abs( amt.intValue() );
            upper = max - amount;
            lower = min + amount;
        }
        
        IntStepper stepper(int point) {
            return new IntStepper(point);
        }
        
        class IntStepper {
            int value;
            IntStepper(int value) { this.value = value; }
            int stepUp() {
                if (upper < value)
                    throw new NoSuchElementException();
                return value += amount;
            }
            int stepDown() {
                if (lower > value)
                    throw new NoSuchElementException();
                return value -= amount;                            
            }
        }
    }

    private static final AbstractStepProvider<Character> charStepProvider =
            new AbstractStepProvider<Character>() {
        @Override public Step<Character> stepFor(Number in) {
            final IntStep step =
                    new IntStep(in, Character.MAX_VALUE, Character.MIN_VALUE);
            return new Step<Character>() {
                public Stepper<Character> stepper(Character point) {
                    final IntStep.IntStepper stepper = step.stepper(point);
                    return new Stepper<Character>() {
                        public Character value()
                            { return (char) stepper.value; }
                        public Character stepUp()
                            { return (char) stepper.stepUp(); }
                        public Character stepDown()
                            { return (char) stepper.stepDown(); }
                    };
                }
            };
        }
    };

    private static final AbstractStepProvider<Byte> byteStepProvider =
            new AbstractStepProvider<Byte>() {
        @Override public Step<Byte> stepFor(Number in) {
            final IntStep step =
                    new IntStep(in, Byte.MAX_VALUE, Byte.MIN_VALUE);
            return new Step<Byte>() {
                public Stepper<Byte> stepper(Byte point) {
                    final IntStep.IntStepper stepper = step.stepper(point);
                    return new Stepper<Byte>() {
                        public Byte value() { return (byte) stepper.value; }
                        public Byte stepUp()
                            { return (byte) stepper.stepUp(); }
                        public Byte stepDown()
                            { return (byte) stepper.stepDown(); }
                    };
                }
            };
        }
    };

    private static final AbstractStepProvider<Short> shortStepProvider =
            new AbstractStepProvider<Short>() {
        @Override public Step<Short> stepFor(Number in) {
            final IntStep step =
                    new IntStep(in, Short.MAX_VALUE, Short.MIN_VALUE);
            return new Step<Short>() {
                public Stepper<Short> stepper(Short point) {
                    final IntStep.IntStepper stepper = step.stepper(point);
                    return new Stepper<Short>() {
                        public Short value() { return (short) stepper.value; }
                        public Short stepUp()
                            { return (short) stepper.stepUp(); }
                        public Short stepDown()
                            { return (short) stepper.stepDown(); }
                    };
                }
            };
        }
    };
    
    private static final AbstractStepProvider<Integer> intStepProvider =
            new AbstractStepProvider<Integer>() {
        @Override public Step<Integer> stepFor(Number in) {
            final IntStep step =
                    new IntStep(in, Integer.MAX_VALUE, Integer.MIN_VALUE);
            return new Step<Integer>() {
                public Stepper<Integer> stepper(Integer point) {
                    final IntStep.IntStepper stepper = step.stepper(point);
                    return new Stepper<Integer>() {
                        public Integer value() { return stepper.value; }
                        public Integer stepUp() { return stepper.stepUp(); }
                        public Integer stepDown() { return stepper.stepDown(); }
                    };
                }
            };
        }
    };

    private static final AbstractStepProvider<Long> longStepProvider =
            new AbstractStepProvider<Long>() {
        @Override public Step<Long> stepFor(Number in) {
            final long amount = Math.abs( in.longValue() );
            final long upper = Long.MAX_VALUE - amount;
            final long lower = Long.MIN_VALUE + amount;
            return new Step<Long>() {
                public Stepper<Long> stepper(final Long point) {
                    return new Stepper<Long>() {
                        long value = point.longValue();

                        public Long value() { return value; }

                        public Long stepUp() {
                            if (upper < value)
                                throw new NoSuchElementException();
                            return value += amount;
                        }

                        public Long stepDown() {
                            if (lower > value)
                                throw new NoSuchElementException();
                            return value -= amount;
                        }
                    };
                }
            };
        }
    };
    
    private static final AbstractStepProvider<Float> floatStepProvider =
            new AbstractStepProvider<Float>() {
        @Override public Step<Float> stepFor(Number in) {
            final float amount = Math.abs( in.floatValue() );
            return new Step<Float>() {
                public Stepper<Float> stepper(Float point) {
                    final float base = point.floatValue();
                    return new Stepper<Float>() {
                        int mult = 0;

                        public Float value() {
                            return base + (mult * amount);
                        }

                        public Float stepUp() {
                            return base + (++mult * amount);
                        }

                        public Float stepDown() {
                            return base + (--mult * amount);
                        }
                    };
                }
            };
        }
    };

    private static final AbstractStepProvider<Double> doubleStepProvider =
            new AbstractStepProvider<Double>() {
        @Override public Step<Double> stepFor(Number in) {
            final double amount = Math.abs( in.doubleValue() );
            return new Step<Double>() {
                public Stepper<Double> stepper(Double point) {
                    final double base = point.doubleValue();
                    return new Stepper<Double>() {
                        long mult = 0;

                        public Double value() {
                            return base + (mult * amount);
                        }

                        public Double stepUp() {
                            return base + (++mult * amount);
                        }

                        public Double stepDown() {
                            return base + (--mult * amount);
                        }
                    };
                }
            };
        }
    };

    private static BigInteger absBigInteger(Number in) {
        if (in instanceof BigInteger) {
            return ((BigInteger)in).abs();
        } else if (in instanceof BigDecimal) {
            return ((BigDecimal)in).toBigInteger().abs();
        } else {
            return BigInteger.valueOf( Math.abs( in.longValue() ) );
        }
    }
        
    private static final AbstractStepProvider<BigInteger>
            BigIntegerStepProvider = new AbstractStepProvider<BigInteger>() {
        @Override public Step<BigInteger> stepFor(Number in) {
            final BigInteger amount = absBigInteger(in);
            return new Step<BigInteger>() {
                public Stepper<BigInteger> stepper(final BigInteger point) {
                    return new Stepper<BigInteger>() {
                        BigInteger value = point;

                        public BigInteger value() { return value; }

                        public BigInteger stepUp() {
                            value = value.add(amount);
                            return value;
                        }

                        public BigInteger stepDown() {
                            value = value.subtract(amount);
                            return value;
                        }
                    };
                }
            };
        }
    };

    private static BigDecimal absBigDecimal(Number in) {
        if (in instanceof BigDecimal) {
            return ((BigDecimal)in).abs();
        } else if (in instanceof BigInteger) {
            return new BigDecimal( ((BigInteger)in).abs() );
        } else {
            return BigDecimal.valueOf( Math.abs( in.doubleValue() ) );
        }
    }

    private static final AbstractStepProvider<BigDecimal>
            BigDecimalStepProvider = new AbstractStepProvider<BigDecimal>() {
        @Override public Step<BigDecimal> stepFor(Number in) {
            final BigDecimal amount = absBigDecimal(in);
            return new Step<BigDecimal>() {
                public Stepper<BigDecimal> stepper(final BigDecimal point) {
                    return new Stepper<BigDecimal>() {
                        BigDecimal value = point;

                        public BigDecimal value() { return value; }

                        public BigDecimal stepUp() {
                            value = value.add(amount);
                            return value;
                        }

                        public BigDecimal stepDown() {
                            value = value.subtract(amount);
                            return value;
                        }
                    };
                }
            };
        }
    };
}
